using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.Text;
using System.IO.Ports;
using System.Threading;
using System.Reflection;
using NetduinoHappyHour.Asynchronous;
using NetduinoHappyHour.Hardware;
using NetduinoHappyHour.Util;
using NetduinoRobot.Common;

namespace NetduinoHappyHour.Behaviour
{
    /// <summary>
    /// Reads commands from com _serialPort and executes them
    /// Written by: Salvador Richter
    /// Appache License Version 2.0 
    /// </summary>
    public class Interactive : BaseBehaviour, IExecutable
    {
        private bool _interactionRunning = true;
        private IExecutable _lastExecutingObject = null;
        private CommandReadWrite _commandReadWrite = null;

        public Interactive()
        {
            _commandReadWrite = new CommandReadWrite(new SerialPortWrapper(SystemConfig.Instance().ComPortName, SystemConfig.Instance().ComPortSpeed));
        }

        /// <summary>
        /// Executes this class
        /// </summary>
        public void Execute()
        {
            while (_interactionRunning)
            {
                ExecuteCommand(_commandReadWrite.ReadXmlCommand());
            }
        }

        /// <summary>
        /// Executes the given command on netduino
        /// </summary>
        /// <param name="command"></param>
        private void ExecuteCommand(String command)
        {
            Object objectToExecute = null;
            
            // check influence of DisplayMessage() on performance
            //DisplayMessage display = new DisplayMessage(command, "");
            //display.Execute();
            objectToExecute = new ObjectFactory().CreateObjectByNameAndParam(command);
            if ((objectToExecute is IExecutable) && !(objectToExecute is Interactive))
            {
                // TODO: check refactoring, maybe keep UpdateRunningcommand as object
                // TODO check if iDisposable creates issue, would make sense for displayMessage but not for CheckBattery
                if (objectToExecute is UpdateRunningCommand)
                {
                    ((UpdateRunningCommand)objectToExecute).ObjectToUpdate = _lastExecutingObject;
                    // parameter update should return imediatelly
                    ((IExecutable)objectToExecute).Execute();
                }
                else
                {
                    // TODO refactor with eg IExecutableAsync
                    if (objectToExecute is DisplayMessage || 
                        objectToExecute is CheckBattery ||
                        objectToExecute is IInteractionResponseMessage)
                    {
                        ((IExecutable)objectToExecute).Execute();
                    }
                    else
                    {
                        _lastExecutingObject = (IExecutable)objectToExecute;
                        // new command need to be exected in background
                        new ExecuteAsync(((IExecutable)objectToExecute)).Execute();
                    }
                }
            }

            if (objectToExecute is IInteractionResponseMessage)
            {
                _commandReadWrite.WriteXmlCommand(((IInteractionResponseMessage)objectToExecute).ResponseMessage());
            }
            
            if (objectToExecute is IDisposable)
            {
                ((IDisposable)objectToExecute).Dispose();
            }
        }
    }
}
